package com.lancoo.znbkxx.teacher.base


import android.app.Application
import androidx.lifecycle.*
import com.lancoo.cpbase.authentication.base.LoginOperate
import com.lancoo.znbkxx.teacher.Ext
import kotlinx.coroutines.*

/**
 * @author : Admin
 * @date   : 2019/7/11 15:10
 * @desc   :
 */
open class BaseViewModel(application: Application) : AndroidViewModel(application),
    LifecycleObserver {

    private val mException: MutableLiveData<Exception> = MutableLiveData()


    private fun launchOnUI(block: suspend CoroutineScope.() -> Unit) {

        viewModelScope.launch { block() }

    }

    suspend fun <T> launchIO(block: suspend CoroutineScope.() -> T) {
        withContext(Dispatchers.IO) {
            block
        }
    }

    fun launch(tryBlock: suspend CoroutineScope.() -> Unit) {
        launchOnUI {
            val loginOperate = LoginOperate(getApplication())
            loginOperate.tokenCheck(Ext.BASE_ADDRESS).let {
                if (it != 1) {
                    loginOperate.reLoginReWrite()
                }
            }
            tryCatch(tryBlock, {

            }, {

            }, true)
        }
    }


    fun launchOnUITryCatch(
        tryBlock: suspend CoroutineScope.() -> Unit,
        catchBlock: suspend CoroutineScope.(Throwable) -> Unit,
        finallyBlock: suspend CoroutineScope.() -> Unit,
        handleCancellationExceptionManually: Boolean
    ) {
        launchOnUI {
            tryCatch(tryBlock, catchBlock, finallyBlock, handleCancellationExceptionManually)
        }
    }

    fun launchOnUITryCatch(
        tryBlock: suspend CoroutineScope.() -> Unit,
        handleCancellationExceptionManually: Boolean = false
    ) {
        launchOnUI {
            tryCatch(tryBlock, {}, {}, handleCancellationExceptionManually)
        }
    }


    private suspend fun tryCatch(
        tryBlock: suspend CoroutineScope.() -> Unit,
        catchBlock: suspend CoroutineScope.(Throwable) -> Unit,
        finallyBlock: suspend CoroutineScope.() -> Unit,
        handleCancellationExceptionManually: Boolean = false
    ) {
        coroutineScope {
            try {
                tryBlock()
            } catch (e: Exception) {
                if (e !is CancellationException || handleCancellationExceptionManually) {
                    mException.value = e
                    catchBlock(e)
                } else {
                    throw e
                }
            } finally {
                finallyBlock()
            }
        }
    }
}